/********************************************
 * MODUL
 * 
 * Name: SUMMARY_PROCESS
 * 
 * Zweck: Fasst die Funktionen zusammen, die zur Ausgabe der abschließenden Zusammenfassung dienen
 * 
 * Autor(en): Simon Hinderhofer, Robert Lehmann, Benjamin Reiner, TIT08
 * 
 ********************************************/

#include <sys/types.h>
#include <stdio.h>
#include <signal.h>	/* für SIGUSR1 */
#include <time.h>

#include "summary_process.h"
#include "tcp_socket_helper.h"

#define TRUE    1
#define FALSE   0

int terminated = FALSE;
int server_socket, client_socket = 0;

/********************************************
 * FUNKTION
 * 
 * Name: sig_handler_summary(int signo)
 * 
 * Zweck: Signalhandling, wird hier genutzt um dem Prozess mitzuteilen, dass das Programm terminiert wurde
 * 
 * Parameter:
 * 	int signo: INPUT, eine signal ID
 * 
 * Globale Variablen:
 * 	int terminated: legt fest, ob das Programm vom Nutzer terminiert wurde
 * 
 * Rückgabewert:
 * 	nicht vorhanden
 * 
 ********************************************/
static void sig_handler_summary(int signo)
{
  if (signo == SIGUSR1) 
  {
    /* teilt do_collect mit, dass sie nicht weiter laufen soll */
    terminated = TRUE;
    
    /* schließe die Sockets */
    close_tcp_socket(server_socket);
    close_tcp_socket(client_socket);

    signal(SIGUSR1, SIG_DFL);
  } 
  else if (signo == SIGINT) 
  {
    signal(SIGINT, SIG_DFL);		/* dass das Programm weiter läuft */
  } 
  else if (signo == SIGUSR2) 
  {
    signal(SIGUSR2, SIG_DFL);
  } 
  else 
  {
    printf("\nreceived signal %d\n\n", signo);
  }

  return;
}

/********************************************
 * FUNKTION
 * 
 * Name: do_collect(const char* host, const ushort port)
 * 
 * Zweck: Hauptfunktion dieses Prozesses. Wartet auf einem socket auf Clientanfragen
 * 	  und speichert die übertragenen Werte
 * 
 * Parameter:
 * 	const char* host: INPUT, IP Adresse auf der der Socket aufgebaut werden soll
 * 	const ushort port: INPUT, zugehöriger Port
 * 
 * Globale Variablen:
 * 	terminated gibt an, ob die Schleife weiter laufen oder der Prozess enden soll
 * 
 * Rückgabewert:
 * 	nicht vorhanden
 * 
 ********************************************/
void do_collect(char* ipc_adress)
{
  int sum_bytes_read = 0;	/* Summe der von allen Proxy Prozessen gelesenen Bytes */
  int sum_bytes_written = 0;	/* Summe der von allen Proxy Prozessen geschriebenen Bytes */
  int sum_proxy_processes = 0;	/* Summe der bereits beendeten Proxy Prozesse */
  char* buffer = NULL;		/* Buffer in den die Nachricht der einzelnen Proxy Prozesse gelesen wird */
  int bytes_read = 0;		/* Anzahl der Bytes, die vom aktuell beendeten Proxy Porzess gelesen wurden */
  int bytes_written = 0;	/* Anzahl der Bytes, die vom aktuell beendeten Proxy Porzess geschrieben wurden */
  
  /* Signalhandler registrieren nach Beispiel aus Vorlesung */
  if (signal(SIGUSR1, sig_handler_summary) == SIG_ERR) 
  {
    fprintf(stderr, "ERROR: cannot catch SIGUSR1\n");
  }
  if (signal(SIGUSR2, sig_handler_summary) == SIG_ERR) 
  {
    fprintf(stderr, "ERROR: cannot catch SIGUSR1\n");
  }
  if (signal(SIGINT, sig_handler_summary) == SIG_ERR) 
  {
    fprintf(stderr, "ERROR: cannot catch SIGINT\n");
  }
  
  /* erstelle einen Socket */
  server_socket = server_create_tcp_ipc_socket(ipc_adress);
  
  while (terminated == FALSE)
  {
    /* Warte auf eingehende Clientverbindungen */
    client_socket = server_accept_tcp_ipc_socket(server_socket);
    
    if (client_socket > 0)
    {
      /* lese vom Socket
      * Da dies IPC ist, wissen wir, wie viele Daten pro
      * Socket ankommen können und es muss nicht wiederholt gelesen werden */
      buffer = read_tcp_socket(client_socket);
      if (buffer == NULL)
      {
	perror("FEHLER beim lesen der Daten");
      }
      
      /* lese die Daten aus */
      if (buffer != NULL)
      {
	sscanf(buffer,"read:%dwrite:%d", &bytes_read, &bytes_written);
      }
      else
      {
	perror("FEHLER beim decodieren der Daten");
      }
      
      /* Addiere die gelesenen Daten auf die Summen auf */
      if (bytes_read > 0 || bytes_written > 0)
      {
	sum_bytes_read = sum_bytes_read + bytes_read;
	sum_bytes_written = sum_bytes_written + bytes_written;
	sum_proxy_processes = sum_proxy_processes + 1;
      }
      
      bytes_read = 0;
      bytes_written = 0;
    }
  }
  
  close_tcp_socket(server_socket);
  close_tcp_socket(client_socket);
  print_summary(sum_bytes_read, sum_bytes_written, sum_proxy_processes);
}

/********************************************
 * FUNKTION
 * 
 * Name: print_summary()
 * 
 * Zweck: Gibt die gesammelten Daten auf der Console aus
 * 
 * Parameter:
 * 	nicht vorhanden
 * 
 * Globale Variablen:
 * 	sum_bytes_read: Summe der gelesenen Bytes
 * 	sum_bytes_write: Summe der geschriebenen Bytes
 * 	sum_proxy_processes: Summe der Proxy Prozesse
 * 
 * Rückgabewert:
 * 	nicht vorhanden
 * 
 ********************************************/
void print_summary(int sum_bytes_read, int sum_bytes_written, int sum_proxy_processes)
{
  printf("Anzahl der gelesenen Bytes: %d\n", sum_bytes_read);
  printf("Anzahl der geschriebenen Bytes: %d\n", sum_bytes_written);
  printf("Anzahl der insgesamt erzeugten Proxy-Prozesse: %d\n", sum_proxy_processes);
}

